﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CoreCms.Net.Auth.HttpContextUser;
using CoreCms.Net.Caching.AutoMate.RedisCache;
using CoreCms.Net.Configuration;
using CoreCms.Net.IRepository;
using CoreCms.Net.IServices;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.FromBody;
using CoreCms.Net.Model.ViewModels.UI;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Nito.AsyncEx;

namespace CoreCms.Net.Web.WebApi.Controllers
{
    /// <summary>
    /// 签到控制器
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class CheckInController : ControllerBase
    {
        private readonly ICoreCmsUserCheckInDetailsServices _userCheckInDetailsServices;
        private readonly IHttpContextUser _user;
        private readonly IRedisOperationRepository _redisOperationRepository;


        /// <summary>
        /// 构造函数
        /// </summary>
        public CheckInController(IHttpContextUser user, ICoreCmsUserCheckInDetailsServices userCheckInDetailsServices, IRedisOperationRepository redisOperationRepository)
        {
            _user = user;
            _userCheckInDetailsServices = userCheckInDetailsServices;
            _redisOperationRepository = redisOperationRepository;
        }


        /// <summary>
        /// 用户签到
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        public async Task<WebApiCallBack> DoUserCheckIn([FromBody] FMDoUserCheckIn entity)
        {
            var jm = new WebApiCallBack();

            var lockKey = "LOCK_DoUserCheckIn:user_" + _user.ID;
            var lockHolder = Guid.NewGuid().ToString("N"); //锁持有者
            var redisUserLock = await _redisOperationRepository.LockTakeAsync(lockKey, lockHolder, TimeSpan.FromSeconds(5));
            if (redisUserLock)
            {
                try
                {
                    var isHave = await _userCheckInDetailsServices.ExistsAsync(p => p.userId == _user.ID && p.checkInData == entity.date);
                    if (isHave)
                    {
                        jm.msg = "今日您已签到";
                        return jm;
                    }
                    var detail = new CoreCmsUserCheckInDetails
                    {
                        userId = _user.ID,
                        checkInData = entity.date,
                        createTime = DateTime.Now
                    };
                    var callBack = await _userCheckInDetailsServices.DoCheckIn(detail);
                    jm.status = callBack.code == 0;
                    jm.msg = callBack.msg;
                    jm.data = callBack.data;
                    return jm;
                }
                catch (Exception e)
                {
                    jm.msg = "数据处理异常";
                    jm.otherData = e;
                }
                finally
                {
                    await _redisOperationRepository.LockReleaseAsync(lockKey, lockHolder);
                }
            }
            else
            {
                jm.msg = "当前请求太频繁_请稍后再试";
            }
            return jm;
        }

        /// <summary>
        /// 获取用户总签到次数
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        public async Task<WebApiCallBack> GetUserCheckCount()
        {
            var jm = new WebApiCallBack
            {
                status = true,
                data = await _userCheckInDetailsServices.GetCountAsync(p => p.userId == _user.ID),
                msg = "获取成功"
            };
            return jm;
        }

        /// <summary>
        /// 获取用户按月签到数据
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Authorize]
        public async Task<WebApiCallBack> GetUserCheckByMonth([FromBody] FMGetUserCheckInByMonth entity)
        {
            var jm = new WebApiCallBack();

            var dt = new DateTime(entity.year, entity.month, 1);

            var min = dt.AddDays(-1);
            var max = dt.AddMonths(1);

            var list = await _userCheckInDetailsServices.QueryListByClauseAsync(p => p.userId == _user.ID && p.checkInData > min && p.checkInData < max);

            var stringArr = list.Select(item => item.checkInData.ToString("yyyy-MM-dd")).ToList();

            jm.status = true;
            jm.data = stringArr;
            jm.msg = "获取成功";

            return jm;
        }
    }
}
